home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / music4c.sit / Music4C Folder / SFInfo folder / SFInfoMain.c < prev    next >
C/C++ Source or Header  |  1990-09-11  |  33KB  |  1,442 lines

  1.  
  2. /*
  3. * Tells about SoundFiles
  4. */
  5.  
  6. #include    "SFInfo.h"
  7. #include    "AIFFType.h"
  8. #include    <stdio.h>
  9. #include    <unix.h>
  10. #include    <string.h>
  11. #include    <math.h>
  12. #include    <SANE.h>
  13. #include    "SFInfoProtos.h"
  14.  
  15.  
  16. int            FileOpen;
  17. long            TotalSamps;
  18. CursHandle    watchCurs;
  19. int            SoundFileType;
  20. long            SampleRate;
  21. long            NumChannels;
  22. double        MaxSample;
  23. double        MinSample;
  24. long            SoundFileDirID;
  25. long            StartUpDirID;
  26. long            fileSize;
  27. Str255        SoundFileName;
  28. Str255        myStr;
  29. ioParam        myIOParmBlk;
  30. Boolean        SDnoResource;
  31. SFReply        SoundFileReply;
  32. WDPBRec        myWDParamBlk;
  33. Point        where;
  34. FileParam        fPB;
  35. Str255    SFDirectoryName;
  36. int            SFSaveVRef;
  37. OSErr        theErr;
  38. Str255        theMess1;
  39. Str255        theMess2;
  40. SysEnvRec    SysEnvData;
  41. int            nrec;
  42.  
  43. /*
  44. * Types used for Sound Designer File format specification
  45. *
  46. *
  47. *    this format seems ok, gg. 8 Nov 88
  48. *
  49. */
  50.  
  51. /*
  52. typedef    enum {    leftSide, rightSide
  53. }    SideType;
  54.  
  55. typedef    enum {
  56.         tTime,SampleNumber,HexSampNum,Volts,Percent,dbm,User
  57. }    ScaleNames;
  58. */
  59.  
  60. typedef    enum {
  61.         Select,Draw,ZoomSelect
  62. }    ModeType;
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. typedef    struct    MarkerType {
  70.             Boolean        Free;            /* Boolean */            
  71.             long        Position;            
  72.             char        Name[34];                
  73. }    MarkerType;
  74.  
  75.  
  76. typedef    struct    EditRecord {
  77.             long        HiAddr;
  78.             long        LoAddr;
  79.             Boolean        ExtendSide;    /* SideType */
  80. }    EditRecord;
  81.  
  82.  
  83. typedef    struct    ZoomType {
  84.             int        v;
  85.             long        h;
  86. }    ZoomType;
  87.  
  88. typedef    struct    ScaleType {
  89.             long            VFactor;
  90.             int            VType;    /* ScaleNames */
  91.             char            VString[34];
  92.             long            HFactor;
  93.             int            HType;    /* ScaleNames */
  94.             char            HString[34];
  95. }    ScaleType;
  96.  
  97.  
  98.  
  99. typedef    struct WaveRec {
  100.             int            HeaderSize;                
  101.             int            Version;
  102.             int            Preview;    /* Boolean */
  103.             WindowPtr    WPtr;
  104.             WindowPeek    WPeek;
  105.  
  106.             long    HInxPage,HInxLine; 
  107.             long    VInxPage,VInxLine; 
  108.             long    HCtlPage,HCtlLine; 
  109.             long    VCtlPage,VCtlLine;
  110.  
  111.             long    VOffset,HOffset;        
  112.             int    VOffConst;
  113.  
  114.             ZoomType        ZF;
  115.             ScaleType        SF;                            
  116.             int        VScrUpdate;
  117.  
  118.             Ptr    BufPtr;
  119.             Size    BufBytes;                            
  120.             long    BufOffset;                    
  121.             RgnHandle    WaveRgn,ClipArea,ScaleArea;
  122.             Rect    CtlWidth;
  123.             ControlHandle    VScroll,HScroll;
  124.  
  125.             Size    FileSize;
  126.             char    BUName[66];                    
  127.             char    FileName[66];                
  128.             int    BURefNum;                    
  129.             int    refNum;                        
  130.             int    vRefNum;
  131.             Boolean    BufChanged;    /* Boolean */
  132.             Boolean    FileChanged;    /* Boolean */
  133.             Boolean    NoBackup;    /* Boolean */
  134.  
  135.             ModeType            Mode;    /* ModeType */
  136.             EditRecord    Edit;
  137.             long            CursorPos;
  138.             RgnHandle    CursorRgn;
  139.             MarkerType    MarkerData[10];    /* 10 */
  140.             long        MarkerOffset;
  141.             long        LoopStart;    
  142.             long        LoopEnd;
  143.             Boolean        ZeroLineOn;    /* Boolean */
  144.             Boolean        CursorOn;    /* Boolean */
  145.             int        ScalesOn;    /* Boolean */
  146.  
  147.             Str255    Comment;    
  148.             long        SampRate;
  149.             long        SampPeriod;
  150.             int        SampSize;
  151.             char        CodeType[34];
  152.  
  153.             Str255    UserStr1;    
  154.             Size        BufSize;            
  155.             long        Loop2Start;
  156.             long        Loop2End;
  157.             SignedByte    Loop1Type;
  158.             SignedByte    Loop2Type;
  159.             int        User4;    
  160. }    WaveRec, *WavPtr;
  161.  
  162.  
  163.  
  164.  
  165. main()
  166. {
  167.  
  168.     SetApplLimit(GetApplLimit());
  169.     MaxApplZone();
  170.     MoreMasters();
  171.     init_process();
  172.     CheckSystem();
  173.     if ( OpenSFRread() ) {
  174.         ShowInfo();
  175.     }
  176.     CloseSF();
  177.     event_loop();
  178.     ExitToShell();    
  179. }    /* main */
  180.  
  181. ProcPtr     restartProc()
  182. {
  183.     ExitToShell();
  184. }
  185.  
  186.  
  187. void    init_process()
  188. {
  189.     init_mgrs();
  190.     init();
  191.     fill_menus();
  192.  
  193. }
  194.  
  195. void    init_mgrs()
  196. {
  197.     InitGraf(&thePort);
  198.     InitFonts();
  199.     FlushEvents(everyEvent, 0 );
  200.     InitWindows();
  201.     InitCursor();
  202.     InitMenus();
  203.     TEInit();
  204.     InitDialogs(restartProc);
  205. }
  206.  
  207. void    init()
  208. {
  209.     SFDirectoryName[0] = 0;
  210.     GetMusic4C_Prefs();
  211.     FileOpen = 0;
  212.     watchCurs = GetCursor(watchCursor);
  213. }
  214.  
  215. void    identify()
  216. {
  217.     DialogPtr    aboutBox;
  218.     EventRecord    event;
  219.     PicHandle    thePic;
  220.     Rect    myRect, tempRect;
  221.     
  222.     
  223.     aboutBox = GetNewDialog(ABOUT_DIALOG, NIL, -1L);
  224.     tempRect.top = aboutBox->portRect.top;
  225.     tempRect.left = aboutBox->portRect.left;
  226.     tempRect.bottom = aboutBox->portRect.bottom;
  227.     tempRect.right = aboutBox->portRect.right;
  228.     tempRect.top = ((screenBits.bounds.bottom - screenBits.bounds.top) - (tempRect.bottom - tempRect.top)) / 2;
  229.     tempRect.left = ((screenBits.bounds.right - screenBits.bounds.left) - (tempRect.right - tempRect.left)) / 2;
  230.     MoveWindow(aboutBox, tempRect.left, tempRect.top, TRUE);
  231.     ParamText("\p", NIL, NIL, NIL);
  232.     ShowWindow(aboutBox);
  233.     SelectWindow(aboutBox);
  234.     DrawDialog(aboutBox);
  235.     SetPort(aboutBox);
  236.     
  237.     
  238.     while( !EventAvail(keyDownMask|autoKeyMask|mDownMask, &event))
  239.         SystemTask();
  240.         
  241.     if ( event.what == mouseDown ) {
  242.         GlobalToLocal(&event.where);
  243.         if ( PtInRect(event.where, &aboutBox->portRect))
  244.             GetNextEvent(mDownMask, &event);
  245.     }
  246.     DisposDialog(aboutBox);
  247. }
  248.  
  249.  
  250.  
  251. void    fill_menus()
  252. {
  253.     
  254.     
  255.     if (GetResource('MENU', APPLE_MENU)==0) {
  256.         SysBeep(20);
  257.         PstringCopy((char *)theMess1,"\pCan't open resource file");
  258.         errorAlert(theMess1, NIL);
  259.         return;
  260.     }
  261.  
  262.     AppendMenu(GetMenu(APPLE_MENU), CtoPstr("About SFInfo..."));
  263.     AppendMenu(GetMenu(APPLE_MENU),  CtoPstr("(-"));
  264.  
  265.     AddResMenu(GetMenu(APPLE_MENU), 'DRVR');
  266.     InsertMenu(GetMenu(APPLE_MENU), 0);
  267.     
  268.     InsertMenu(GetMenu(FILE_MENU), 0);
  269.     DisableItem(GetMHandle(FILE_MENU), 2);
  270.     
  271.     DrawMenuBar();
  272. }
  273.  
  274.  
  275.  
  276.  
  277.  
  278. void    event_loop()
  279. {
  280.     EventRecord    event;
  281.     char    c;
  282.  
  283.     FlushEvents(everyEvent, 0 );
  284.     while (TRUE) {    
  285.         while(GetNextEvent(everyEvent, &event)) {
  286.             SystemTask();    /* do DA's */
  287.             switch(event.what) {
  288.                 case mouseDown:
  289.                     do_mouse_down(&event);
  290.                     break;
  291.                 case mouseUp:
  292.                     break;
  293.                 case keyDown:
  294.                     c = event.message & charCodeMask;
  295.                     if(event.modifiers & cmdKey)
  296.                         do_menu(MenuKey(c));
  297.                     break;
  298.                 case keyUp:
  299.                     break;
  300.                 case autoKey:
  301.                     break;
  302.                 case updateEvt:
  303.                 case diskEvt:
  304.                     break;
  305.                 case activateEvt:
  306.                     break;
  307.                 case networkEvt:
  308.                 case driverEvt:
  309.                 case app1Evt:
  310.                 case app2Evt:
  311.                 case app3Evt:
  312.                 case app4Evt:
  313.                 default:
  314.                     break;
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320.  
  321. void    do_mouse_down(event)
  322.     EventRecord    *event;
  323. {
  324.     WindowPtr    windowp;
  325.     int    windowCode = FindWindow(MK_LONG(event->where), &windowp);
  326.     
  327.     
  328.     switch(windowCode) {
  329.         case inDesk:
  330.             break;
  331.         case inMenuBar:
  332.             do_menu(MenuSelect(MK_LONG(event->where)));
  333.             break;
  334.         case inSysWindow:
  335.             SystemClick(event, windowp);
  336.             break;
  337.         case inContent:
  338.             break;
  339.         case inDrag:
  340.             break;
  341.         case inGrow:
  342.             break;
  343.         case inGoAway:
  344.             break;
  345.         default:
  346.             break;
  347.     }
  348. }
  349.  
  350.  
  351. void    do_menu(command)
  352.     long    command;
  353. {
  354.     int    menu_id = HiWord(command);
  355.     int    item    = LoWord(command);
  356.     char    item_name[32];
  357.     
  358.     switch(menu_id) {
  359.         case APPLE_MENU:
  360.             if ( item == AboutItem)
  361.                 identify();
  362.             else {
  363.                 GetItem(GetMHandle(menu_id), item, item_name);
  364.                 OpenDeskAcc(item_name);
  365.             }
  366.             break;
  367.         case FILE_MENU:
  368.             switch(item) {
  369.                 case OPEN:
  370.                     if ( OpenSFRread() ) {
  371.                         ShowInfo();
  372.                     }
  373.                     CloseSF();
  374.                 break;
  375.                 case QUIT:
  376.                     Finish();
  377.                     break;
  378.             }
  379.             break;
  380.     }
  381.     HiliteMenu(0);
  382. }
  383.  
  384. void    Finish()
  385. {
  386.     ExitToShell();
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395. Boolean    OpenSFRread()
  396. {
  397.  
  398.     SFTypeList    types;
  399.     extern        ioParam        myIOParmBlk;
  400.     extern        Str255        SoundFileName;
  401.     extern        long        StartUpDirID;
  402.     extern        long        SoundFileDirID;
  403.     extern        int            SFSaveVRef;
  404.     extern        long        fileSize;
  405.     extern        int            SoundFileType;
  406.     extern        long        NumChannels;
  407.     extern        double        MaxSample;
  408.     extern        double        MinSample;
  409.     extern        Boolean        SDnoResource;
  410.     extern        Str255        SFDirectoryName;
  411.     long            sfResFileRefNum;
  412.     Str255            resString;
  413.     Str255            myString;
  414.     Handle            myHndl;
  415.     StringHandle    aString;
  416.     int                wdRefNum;
  417.     int                i;
  418.     char            c0, c1, c2, c3;
  419.     
  420.     if ( SFDirectoryName[0] != NIL ) {
  421.         if ( !SetSFDir(SFDirectoryName, &SoundFileDirID) ) {
  422.             CurDirStore = StartUpDirID;
  423.             return(FALSE);
  424.         }
  425.     }
  426.  
  427.     SetPt(&where, 100, 100);
  428.     SFGetFile(where, NIL, NIL, -1, NIL, NIL, &SoundFileReply);
  429.     if(!SoundFileReply.good) {
  430.         CurDirStore = StartUpDirID;
  431.         return(FALSE);
  432.     }
  433.     GetSFDir(&SFDirectoryName);
  434.     /* we now have the directory where the sound file is to be created */
  435.     SetSFDir(SFDirectoryName, &SoundFileDirID);
  436.  
  437.     SFSaveVRef = SoundFileReply.vRefNum;
  438.     PstringCopy((char *)SoundFileName, (char *)SoundFileReply.fName);
  439.     myIOParmBlk.ioNamePtr = (StringPtr)SoundFileName;
  440.     myIOParmBlk.ioVRefNum = SoundFileReply.vRefNum;
  441.     myIOParmBlk.ioVersNum = SoundFileReply.version;
  442.  
  443.     myIOParmBlk.ioPermssn = fsRdWrPerm;
  444.     if ( (theErr = PBOpen(&myIOParmBlk, FALSE) )!= noErr) {
  445.         PstringCopy((char *)theMess1,"\pError opening file");
  446.         errorAlert(theMess1, NIL);
  447.     }
  448.     myIOParmBlk.ioCompletion = NIL;
  449.     PBGetEOF(&myIOParmBlk, FALSE);
  450.     if ( (fileSize = (long)myIOParmBlk.ioMisc) <= 0 ) {
  451.         PstringCopy((char *)theMess1,"\pFile is empty!");
  452.         errorAlert(theMess1, NIL);
  453.         return(FALSE);
  454.     }
  455.     
  456.     
  457.     /* now read the resource part */
  458.     /* first check if it is a Sound Designer file */
  459.     fPB.ioCompletion = (ProcPtr)NIL;
  460.     fPB.ioNamePtr = myIOParmBlk.ioNamePtr;
  461.     fPB.ioVRefNum = myIOParmBlk.ioVRefNum;
  462.     fPB.ioFVersNum = myIOParmBlk.ioVersNum;
  463.     fPB.ioFDirIndex = NIL;
  464.     theErr = PBGetFInfo(&fPB, FALSE);
  465.     
  466.     if ( (fPB.ioFlFndrInfo.fdType == 'TEXT') && (fPB.ioFlFndrInfo.fdCreator = 'MU4C' ) )
  467.             SoundFileType = FLOAT;
  468.     else if ( fPB.ioFlFndrInfo.fdType == 'SFIL' )
  469.         SoundFileType = SD1;
  470.     else if ( fPB.ioFlFndrInfo.fdType == 'Sd2f' )
  471.             SoundFileType = SD2;
  472.     else if ( fPB.ioFlFndrInfo.fdType == 'AIFF' )
  473.             SoundFileType = AIFF;
  474.     else {
  475.         PstringCopy((char *)theMess1, "\pUnknown sound file type");
  476.         sprintf((char *)theMess2, "%c%c%c%c",
  477.             (char)((fPB.ioFlFndrInfo.fdType & 0xFF000000) >> 24),
  478.             (char)((fPB.ioFlFndrInfo.fdType & 0x00FF0000) >> 16),
  479.             (char)((fPB.ioFlFndrInfo.fdType & 0x0000FF00) >> 8),
  480.             (char)(fPB.ioFlFndrInfo.fdType & 0x000000FF));
  481.         CtoPstr((char *)theMess2);
  482.         errorAlert(theMess1, theMess2);
  483.         return(FALSE);
  484.     }
  485.             
  486.  
  487.  
  488.  
  489.  
  490.     sfResFileRefNum = OpenResFile(SoundFileName);
  491.     SDnoResource = FALSE;
  492.     if ((theErr = ResError()) != noErr) {
  493.         if ( SoundFileType != SD1 && SoundFileType != SD1 && SoundFileType != AIFF) {
  494.             PstringCopy((char *)theMess1, "\pError opening resource file: ");
  495.             OSError2(theMess1, SoundFileName, theErr);
  496.             return(FALSE);
  497.         }
  498.         else {
  499.             SDnoResource = TRUE;
  500.         }
  501.         return(TRUE);
  502.     }
  503.     else {
  504.         GetIndString(&resString, SFRESOURCENUM, 1);
  505.         PtoCstr((char *)resString);
  506.         if ( strcmp("FLOAT", (char *)resString) == 0 ) {
  507.             SoundFileType = FLOAT;
  508.         }
  509.         else if ( strcmp("INT16", (char *)resString) == 0 ) {
  510.             SoundFileType = INT16;
  511.         }
  512.         else if ( strcmp("SD", (char *)resString) == 0 )
  513.             SoundFileType = SD1;
  514.         else if ( strcmp("SD1", (char *)resString) == 0 )
  515.             SoundFileType = SD1;
  516.         else if ( strcmp("SD2", (char *)resString) == 0 ) {
  517.             SoundFileType = SD2;
  518.             myHndl = GetResource('STR ', SAMPLE_RATE_RES );
  519.             if ( myHndl && (theErr = ResError()) == noErr) {
  520.                 aString = (StringHandle)GetString(SAMPLE_RATE_RES);
  521.                 HLock(aString);
  522.                 PstringCopy((char *)myString, (char *)*aString);
  523.                 PtoCstr((char *)myString);
  524.                 /* "cast" to integer value */
  525.                 i = strcspn((char *)myString, ".");
  526.                 if ( i > 0 )
  527.                     myString[i] = '\0';
  528.                 CtoPstr((char *)myString);
  529.                 StringToNum(myString, &SampleRate);
  530.                 HUnlock(aString);
  531.                 DisposHandle(aString);
  532.                 SoundFileType = SD2;
  533.                 myHndl = GetResource('STR ', SAMPLE_CHANNELS_RES );
  534.                 if ((theErr = ResError()) == noErr) {
  535.                     aString = (StringHandle)GetString(SAMPLE_CHANNELS_RES);
  536.                     HLock(aString);
  537.                     StringToNum(*aString, &NumChannels);
  538.                     HUnlock(aString);
  539.                 }
  540.                 DisposHandle(aString);
  541.                 DisposHandle(myHndl);
  542.             }
  543.             else
  544.                 SDnoResource = TRUE;
  545.         }
  546.         else if ( strcmp("AIFF", (char *)resString) == 0 ) {
  547.             SoundFileType = AIFF;
  548.         }
  549.         else if ( strcmp("", (char *)resString) == 0 ) {
  550.             myHndl = GetResource('STR ', SAMPLE_RATE_RES );
  551.             if ( myHndl && (theErr = ResError()) == noErr) {
  552.                 aString = (StringHandle)GetString(SAMPLE_RATE_RES);
  553.                 HLock(aString);
  554.                 PstringCopy((char *)myString, (char *)*aString);
  555.                 PtoCstr((char *)myString);
  556. /* "cast" to integer value */
  557.                 i = strcspn((char *)myString, ".");
  558.                 if ( i > 0 )
  559.                     myString[i] = '\0';
  560.                 CtoPstr((char *)myString);
  561.                 StringToNum(myString, &SampleRate);
  562.                 HUnlock(aString);
  563.                 DisposHandle(aString);
  564.                 SoundFileType = SD2;
  565.                 myHndl = GetResource('STR ', SAMPLE_CHANNELS_RES );
  566.                 if ((theErr = ResError()) == noErr) {
  567.                     aString = (StringHandle)GetString(SAMPLE_CHANNELS_RES);
  568.                     HLock(aString);
  569.                     StringToNum(*aString, &NumChannels);
  570.                     HUnlock(aString);
  571.                 }
  572.                 DisposHandle(aString);
  573.                 DisposHandle(myHndl);
  574.             }
  575.             else if (SoundFileType != AIFF)
  576.                 SoundFileType = SD1;
  577.             SDnoResource = TRUE;
  578.             CloseResFile(sfResFileRefNum);
  579.             return(TRUE);
  580.         }
  581.         else {
  582.             CtoPstr((char *)resString);
  583.             PstringCopy((char *)theMess1,"\pUnknown Sound file type");
  584.             errorAlert(theMess1, resString);
  585.             return(FALSE);
  586.         }
  587.  
  588.         GetIndString(&resString, SFRESOURCENUM, 2);
  589.         StringToNum(resString, &NumChannels);
  590.         if ( NumChannels > 4L ) {
  591.             PstringCopy((char *)theMess1,"\pmono, stereo or quad soundfiles");
  592.             errorAlert(theMess1, NIL);
  593.             CloseResFile(sfResFileRefNum);
  594.             return(FALSE);
  595.         }
  596.  
  597.         GetIndString(&resString, SFRESOURCENUM, 3);
  598.         StringToNum(resString, &SampleRate);
  599.         
  600.         GetIndString(&resString, SFRESOURCENUM, 4);
  601.         PtoCstr((char *)resString);
  602.         sscanf((char *)resString, "%lf", &MaxSample);
  603.  
  604.         GetIndString(&resString, SFRESOURCENUM, 5);
  605.         PtoCstr((char *)resString);
  606.         sscanf((char *)resString, "%lf", &MinSample);
  607.         CloseResFile(sfResFileRefNum);
  608.     }
  609.     CloseResFile(sfResFileRefNum);
  610.     return(TRUE);
  611. }
  612.  
  613.  
  614.  
  615.  
  616. void    ShowInfo()
  617. {
  618.     DialogPtr    myDialog;
  619.     int        itemHit;
  620.     Str255    theString;
  621.     int        itype;
  622.     Handle    hndl;
  623.     Rect        box;
  624.     long    nSamps;
  625.     double    theTime;
  626.     extern    CursHandle    watchCurs;
  627.     int    i;
  628.     Rect    tempRect;
  629.  
  630.     SetCursor(*watchCurs);
  631.  
  632.     /* put up the dialog box with the info */
  633.     myDialog = GetNewDialog(InfoDialog, NIL, (WindowPtr) -1);
  634.     tempRect.top = myDialog->portRect.top;
  635.     tempRect.left = myDialog->portRect.left;
  636.     tempRect.bottom = myDialog->portRect.bottom;
  637.     tempRect.right = myDialog->portRect.right;
  638.     tempRect.top = ((screenBits.bounds.bottom - screenBits.bounds.top) - (tempRect.bottom - tempRect.top)) / 2;
  639.     tempRect.left = ((screenBits.bounds.right - screenBits.bounds.left) - (tempRect.right - tempRect.left)) / 2;
  640.     MoveWindow(myDialog, tempRect.left, tempRect.top, TRUE);
  641.     ParamText("\p", NIL, NIL, NIL);
  642.     ShowWindow(myDialog);
  643.     SelectWindow(myDialog);
  644.     DrawDialog(myDialog);
  645.     SetPort(myDialog);
  646.     
  647.     /* figure it all out */
  648.     GetDItem(myDialog, TypeItem, &itype, &hndl, &box);
  649.     switch(SoundFileType) {
  650.         case    FLOAT:
  651.             PstringCopy((char *)theString, "\pFLOAT");
  652.             break;
  653.         case    INT16:
  654.             PstringCopy((char *)theString, "\pINT16");
  655.             break;
  656.         case    SD1:
  657.             PstringCopy((char *)theString, "\pSound Designer");/* ????? */
  658.             break;
  659.         case    SD2:
  660.             PstringCopy((char *)theString, "\pSound Designer II");
  661.             break;
  662.         case    AIFF:
  663.             PstringCopy((char *)theString, "\pAIFF");
  664.             break;
  665.         default:
  666.             PstringCopy((char *)theString, "\p");
  667.             break;
  668.     }
  669.     SetIText(hndl, theString);
  670.     
  671.  
  672.     switch(SoundFileType) {
  673.         case    FLOAT:
  674.             nSamps = fileSize / sizeof(float);
  675.             if ( NumChannels > 0 )
  676.                 nSamps /= NumChannels;
  677.             else
  678.                 NumChannels = 1L;
  679.             theTime = (double)nSamps / SampleRate;
  680.             break;
  681.         case    INT16:
  682.             nSamps = fileSize / sizeof(int);
  683.             if ( NumChannels > 0 )
  684.                 nSamps /= NumChannels;
  685.             else
  686.                 NumChannels = 1L;
  687.             theTime = (double)nSamps / SampleRate;
  688.             break;
  689.         case    SD2:
  690.             if ( !SD2Info() )
  691.                 break;
  692.             nSamps = fileSize / sizeof(int);
  693.             theTime = (double)nSamps / SampleRate / NumChannels;
  694.             break;
  695.         case    SD1:
  696.             if ( !SD1Info() )
  697.                 break;
  698.             nSamps = fileSize / sizeof(int);
  699.             theTime = (double)nSamps / SampleRate;
  700.             NumChannels = 1L;
  701.             break;
  702.         case    AIFF:
  703.             if (!AIFFInfo() )
  704.                 break;
  705.             nSamps = fileSize / sizeof(int);
  706.             theTime = (double)nSamps / SampleRate;
  707.             break;
  708.         default:
  709.             nSamps = 0L;
  710.             theTime = 0.0;
  711.             break;
  712.     }
  713.     
  714.     GetDItem(myDialog, ChanItem, &itype, &hndl, &box);
  715.     NumToString(NumChannels, &theString);
  716.     SetIText(hndl, theString);
  717.  
  718.     GetDItem(myDialog, SrateItem, &itype, &hndl, &box);
  719.     NumToString(SampleRate, &theString);
  720.     SetIText(hndl, theString);
  721.     GetDItem(myDialog, MaxAmpItem, &itype, &hndl, &box);
  722.     sprintf((char *)theString, "%lf", MaxSample);
  723.     CtoPstr((char *)theString);
  724.     SetIText(hndl, theString);
  725.     
  726.     GetDItem(myDialog, MinAmpItem, &itype, &hndl, &box);
  727.     sprintf((char *)theString, "%lf", MinSample);
  728.     CtoPstr((char *)theString);
  729.     SetIText(hndl, theString);
  730.  
  731.     /* calculate file duration */
  732.     if ( fileSize == 0L ) {
  733.         GetDItem(myDialog, LengthTimeItem, &itype, &hndl, &box);
  734.         PstringCopy((char *)theString, "\p0");
  735.         SetIText(hndl, theString);
  736.  
  737.         GetDItem(myDialog, LengthSampsItem, &itype, &hndl, &box);
  738.         PstringCopy((char *)theString, "\p0");
  739.         SetIText(hndl, theString);
  740.     }
  741.     else {
  742.             GetDItem(myDialog, LengthTimeItem, &itype, &hndl, &box);
  743.             i = sprintf((char *)theString, "%lf", theTime);
  744.             CtoPstr((char *)theString);
  745.             SetIText(hndl, theString);
  746.             
  747.             GetDItem(myDialog, LengthSampsItem, &itype, &hndl, &box);
  748.             NumToString(nSamps, &theString);
  749.             SetIText(hndl, theString);
  750.     }
  751.     GetDItem(myDialog, TitleItem, &itype, &hndl, &box);
  752.     SetIText(hndl, SoundFileReply.fName);
  753.  
  754.     InitCursor();
  755.     ShowWindow((WindowPtr)myDialog);
  756.     OutLineButton(myDialog, theUserItem);
  757.     
  758.     itemHit = 0;
  759.     while ( itemHit != OKButton) 
  760.         ModalDialog((ProcPtr)NIL, &itemHit);
  761.  
  762.     DisposDialog(myDialog);
  763. }
  764.  
  765. Boolean    CloseSF()
  766. {
  767.     extern        ioParam        myIOParmBlk;
  768.     extern        ioParam        NewParmBlk;
  769.     
  770.     if ( (theErr = PBClose(&myIOParmBlk, FALSE)) != noErr ) { 
  771. /*        PstringCopy((char *)theMess1,"\pError closing Sound File: ", SoundFileName, theErr);*/
  772.         return(FALSE);
  773.     }
  774.     fPB.ioCompletion = (ProcPtr)NIL;
  775.     fPB.ioNamePtr = myIOParmBlk.ioNamePtr;
  776.     fPB.ioVRefNum = myIOParmBlk.ioVRefNum;
  777.     fPB.ioFVersNum = myIOParmBlk.ioVersNum;
  778.     fPB.ioFDirIndex = NIL;
  779.     if ( (theErr =     PBFlushVol(&fPB, FALSE)) != noErr ) { 
  780.         PstringCopy((char *)theMess1,"\pError returned from PBFlushVol for sample file's volume:");
  781.         NumToString(theErr, &theMess2);
  782.         OSError(theMess1, theMess2);
  783.         return(FALSE);
  784.     }
  785.     
  786.     return(TRUE);
  787. }
  788.  
  789.  
  790.  
  791. Boolean    SetSFDir(DirName, theDirID)
  792.     Str255        DirName;
  793.     long        *theDirID;
  794. {
  795.     extern        int            SFSaveVRef;
  796.     extern        int            ReportFileRefNum;
  797.     Str255        aString;
  798.     
  799.     
  800.     PstringCopy((char *)aString, (char *)DirName);
  801.     myWDParamBlk.ioNamePtr = (StringPtr)aString;
  802.     myWDParamBlk.ioCompletion = NIL;
  803.     myWDParamBlk.ioVRefNum = 0;
  804.     myWDParamBlk.ioWDDirID = NIL;
  805.  
  806.     if ( (theErr = PBHSetVol(&myWDParamBlk, FALSE)) != noErr ) {
  807. /*        OSError2("\pSetSFDir error: PBHSetVol", myWDParamBlk.ioNamePtr, (long)theErr);
  808.         return(FALSE);
  809. */
  810.     }
  811.     
  812.     PBHGetVol(&myWDParamBlk, FALSE);
  813.  
  814.     *theDirID = myWDParamBlk.ioWDDirID;
  815.     CurDirStore = *theDirID;
  816.     
  817.     SFSaveVRef = myWDParamBlk.ioVRefNum;
  818.     SFSaveDisk = -1 * SFSaveVRef;
  819.     return(TRUE);
  820. }
  821.  
  822.  
  823. void    OutLineButton(theDialog, itemNo)
  824.     DialogPtr    theDialog;
  825.     int        itemNo;
  826. {
  827.     int        itype;
  828.     Rect        buttonRect;
  829.     Handle    aHandl;
  830.     GrafPtr    tempPort;
  831.     
  832.     GetPort(&tempPort);
  833.     SetPort(theDialog);
  834.     GetDItem(theDialog, itemNo, &itype, &aHandl, &buttonRect);
  835.     PenSize(3,3);
  836.     InsetRect(&buttonRect, -4, -4); 
  837.     FrameRoundRect(&buttonRect, 16, 16);
  838.     PenSize(1,1);
  839.     SetPort(tempPort);
  840. }     
  841.  
  842.     
  843. void    OSError(msg1, msg2)
  844.     Str255    msg1, msg2;
  845. {
  846.     short    i;
  847.     if (msg2[0] != 0)
  848.         ParamText(msg1, msg2, "\p", "\p");
  849.     else
  850.         ParamText(msg1, "\p", "\p", "\p");
  851.     i = CautionAlert(401, NIL);
  852. }
  853.  
  854. void    OSError2(msg1, msg2, errNum)
  855.     Str255    msg1, msg2;
  856.     long    errNum;
  857. {
  858.     Str255    numMsg;
  859.     short    i;
  860.     
  861.     NumToString((long)errNum, &numMsg);
  862.     ParamText(msg1, msg2, numMsg, NIL);
  863.     i = CautionAlert(401, NIL);
  864. }
  865.  
  866. void    DoOSErrorAlert(mess1, mess2)
  867.     Str255 mess1, mess2;
  868. {
  869.     ParamText(mess1, mess2, NIL, NIL);
  870.     CautionAlert(401, NIL);
  871. }
  872.  
  873.  
  874. void    PstringCopy(to, from)
  875.     char    *to, *from;
  876. {
  877.     char    *end = from + *from + 1;
  878.     for ( *to++ = *from++; from < end; )
  879.         *to++ = *from++;
  880. }
  881.  
  882.  
  883. void    PstringCat(to, from)
  884.     char    *to, *from;
  885. {
  886.     register int i, length;
  887.     char    *p;
  888.     
  889.     length = *from;
  890.     p = to + *to + 1;
  891.     from++;
  892.     for ( i = 0; i < length; i++)    *p++ = *from++;
  893.     *to += length;
  894. }
  895.  
  896.  
  897. /*-------------------------------------------------------------------------------*/
  898.  
  899.  
  900. int    stcisn(s, set)
  901. register char *s;
  902. char *set;
  903.  
  904. {
  905. register char *t;
  906. register int count = 0;
  907. /* find position of set in s */
  908.     while (*s)
  909.     {
  910.         t = set;
  911.         while (*t && (*s != *t)) t++;
  912.         if (!*t)
  913.         {
  914.             s++;
  915.             count++;
  916.         }
  917.         else
  918.             break;
  919.     }
  920.     
  921.     return (count);
  922. }
  923.  
  924.  
  925.  
  926. void    errorAlert(mess1, mess2)
  927.     Str255 mess1, mess2;
  928. {
  929.     if ( mess2 )
  930.         ParamText(mess1, mess2, "\p", "\p");
  931.     else
  932.         ParamText(mess1, "\p", "\p", "\p");
  933.     CautionAlert(401, NIL);
  934. }
  935.  
  936.  
  937.  
  938. Boolean    AIFFInfo()
  939. {
  940.     register        long    i;
  941.     register        double    scalefactor;
  942.     register        double    x;
  943.     double            peak;
  944.     int                *theIbuf, *Iptr;
  945.     float            *sp, *SampBuf;
  946.     long            nBytes;
  947.     long            nSamps;
  948.     long            bytesLeft;
  949.     long            sampBufsz;
  950.     Chunk            FormChunkHeader, *FormChunkHeaderPtr;
  951.     CommonChunk        CommonHeader, *CommonHeaderPtr;
  952.     SoundDataChunk    SoundDataHeader, *SoundDataHeaderPtr;
  953.     BasicChunk        BaseChunk, *BaseChunkPtr;
  954.     long            aLong, *aLongPtr;
  955.     Boolean            found;
  956.     Fixed            aFix;
  957.     decform            mydecform;
  958.     Str255            myStr255;
  959.     long            RecLength;
  960.  
  961.     FormChunkHeaderPtr = &FormChunkHeader;
  962.     CommonHeaderPtr = &CommonHeader;
  963.     SoundDataHeaderPtr = &SoundDataHeader;
  964.  
  965.  
  966.     myIOParmBlk.ioCompletion = 0L;
  967.     myIOParmBlk.ioPosMode = fsFromStart;
  968.     myIOParmBlk.ioPosOffset = 0L;
  969.     theErr = PBSetFPos(&myIOParmBlk, FALSE);
  970.  
  971.  
  972.  
  973.     myIOParmBlk.ioBuffer = (Ptr)FormChunkHeaderPtr;
  974.     myIOParmBlk.ioReqCount = sizeof(FormChunkHeader);
  975.     theErr = PBRead(&myIOParmBlk, FALSE);
  976.     if ( FormChunkHeader.ckID != 'FORM' ) {
  977.         PstringCopy((char *)theMess1, "\pError reading AIFF file, FORM header");
  978.         DoOSErrorAlert(theMess1, NIL);
  979.         return(FALSE);
  980.     }
  981.  
  982.  
  983.     BaseChunkPtr = &BaseChunk;
  984.     found = FALSE;
  985.  
  986.     while ( !found ) {
  987.         myIOParmBlk.ioBuffer = (Ptr)BaseChunkPtr;
  988.         myIOParmBlk.ioReqCount = sizeof(BaseChunk);
  989.         theErr = PBRead(&myIOParmBlk, FALSE);
  990.         if ( theErr == eofErr ) {
  991.             DoOSErrorAlert("\pError: EOF reading reading AIFF file, no COMM header", NIL);
  992.             return(FALSE);
  993.         }
  994.         if ( BaseChunk.ckID == 'COMM' ) {
  995.             found = TRUE;
  996.             myIOParmBlk.ioPosMode = fsFromMark;
  997.             myIOParmBlk.ioPosOffset = -myIOParmBlk.ioActCount;
  998.             theErr = PBSetFPos(&myIOParmBlk, FALSE);
  999.             myIOParmBlk.ioPosMode = fsAtMark;
  1000.         /* get the common chunk info */
  1001.             myIOParmBlk.ioBuffer = (Ptr)CommonHeaderPtr;
  1002.             myIOParmBlk.ioReqCount = sizeof(CommonHeader);
  1003.             theErr = PBRead(&myIOParmBlk, FALSE);
  1004.  
  1005.             aFix = X2Fix( &CommonHeader.sampleRate);
  1006.             SampleRate = (long) aFix;
  1007.             mydecform.style = 1;
  1008.             mydecform.digits = -1;
  1009.             num2str(&mydecform, CommonHeader.sampleRate, &myStr255);
  1010.             StringToNum(myStr255, &SampleRate );
  1011.             NumChannels = CommonHeader.numChannels;
  1012.         }
  1013.         else {    /* skip this chunk */
  1014.             myIOParmBlk.ioPosMode = fsFromMark;
  1015.             myIOParmBlk.ioPosOffset = BaseChunk.ckSize;
  1016.             theErr = PBSetFPos(&myIOParmBlk, FALSE);
  1017.             if ( theErr == eofErr ) {
  1018.                 DoOSErrorAlert("\pError: EOF reading reading AIFF file, no COMM header", NIL);
  1019.                 return(FALSE);
  1020.             }
  1021.             myIOParmBlk.ioPosMode = fsAtMark;
  1022.         }
  1023.  
  1024.     }
  1025.  
  1026.     /* rewind to start of FORM */
  1027.     myIOParmBlk.ioPosMode = fsFromStart;
  1028.     myIOParmBlk.ioPosOffset = sizeof(FormChunkHeader);
  1029.     theErr = PBSetFPos(&myIOParmBlk, FALSE);
  1030.     if ( theErr != noErr ) {
  1031.             DoOSErrorAlert("\pError re-positioning file to start of FORM", NIL);
  1032.         return(FALSE);
  1033.     }
  1034.  
  1035.     /* now look for SSND Chunk */
  1036.     found = FALSE;
  1037.  
  1038.     while ( !found ) {
  1039.         myIOParmBlk.ioBuffer = (Ptr)BaseChunkPtr;
  1040.         myIOParmBlk.ioReqCount = sizeof(BaseChunk);
  1041.         theErr = PBRead(&myIOParmBlk, FALSE);
  1042.         if ( theErr == eofErr ) {
  1043.             DoOSErrorAlert("\pError: EOF reading reading AIFF file, no SSND header", NIL);
  1044.             return(FALSE);
  1045.         }
  1046.         if ( BaseChunk.ckID == 'SSND' ) {
  1047.             found = TRUE;
  1048.             myIOParmBlk.ioPosMode = fsFromMark;
  1049.             myIOParmBlk.ioPosOffset = -myIOParmBlk.ioActCount;
  1050.             theErr = PBSetFPos(&myIOParmBlk, FALSE);
  1051.             myIOParmBlk.ioPosMode = fsAtMark;
  1052.         /* get the common chunk info */
  1053.             myIOParmBlk.ioBuffer = (Ptr)SoundDataHeaderPtr;
  1054.             myIOParmBlk.ioReqCount = sizeof(SoundDataHeader);
  1055.             theErr = PBRead(&myIOParmBlk, FALSE);
  1056.         }
  1057.         else {    /* skip this chunk */
  1058.             myIOParmBlk.ioPosMode = fsFromMark;
  1059.             myIOParmBlk.ioPosOffset = BaseChunk.ckSize;
  1060.             theErr = PBSetFPos(&myIOParmBlk, FALSE);
  1061.             if ( theErr == eofErr ) {
  1062.                 DoOSErrorAlert("\pError reading AIFF file, no SSND header", NIL);
  1063.                 return(FALSE);
  1064.             }
  1065.             myIOParmBlk.ioPosMode = fsAtMark;
  1066.         }
  1067.  
  1068.     };
  1069.  
  1070. /* we only get here if we have found FORM, COMM and SSND chunks */
  1071.         RecLength = (long)16384;
  1072.         nrec = 0;
  1073.         scalefactor = 2.0/65535.0;
  1074.         MinSample = 0.0;
  1075.         MaxSample = 0.0;
  1076.         sampBufsz  = RecLength  / sizeof(int);
  1077.         theIbuf = (int *)NewPtr(sizeof(int) * sampBufsz);
  1078.         if ( (theErr = MemError()) != noErr ) {
  1079.             DoOSErrorAlert("\pcan't get enough memory  for theIbuf", NIL);
  1080.             return(FALSE);
  1081.         }
  1082.         SampBuf = (float *)NewPtr( sizeof(float) * sampBufsz);
  1083.         if ( (theErr = MemError()) != noErr ) {
  1084.             DoOSErrorAlert("\pcan't get enough memory  for SampBuf", NIL);
  1085.             return(FALSE);
  1086.         }
  1087.  
  1088.  
  1089.  
  1090.         bytesLeft = SoundDataHeader.ckSize - sizeof(SoundDataHeader.offset)
  1091.                         - sizeof(SoundDataHeader.blockSize);
  1092.         fileSize = bytesLeft;
  1093.         myIOParmBlk.ioPosMode = fsAtMark;
  1094.         myIOParmBlk.ioPosOffset = NIL;
  1095.  
  1096.         while ( bytesLeft > 0L ) {
  1097.             if ( bytesLeft > RecLength )
  1098.                 nBytes = RecLength;
  1099.             else
  1100.                 nBytes = bytesLeft;
  1101.  
  1102.             myIOParmBlk.ioBuffer = (Ptr)theIbuf;
  1103.             myIOParmBlk.ioReqCount = nBytes;
  1104.             theErr = PBRead(&myIOParmBlk, FALSE);
  1105.             if (theErr != noErr ) {
  1106.                 if ( theErr == eofErr )
  1107.                     DoOSErrorAlert("\pEnd of file reached", NIL);
  1108.             }
  1109.             nBytes = myIOParmBlk.ioActCount;
  1110.             if ( nBytes != myIOParmBlk.ioReqCount ) {
  1111.                 if ( theErr != eofErr ) {
  1112.                     DoOSErrorAlert("\pRead less bytes than expected", NIL);
  1113.                 }
  1114.                 if ( nBytes == 0L ) {
  1115.                     DisposPtr((Ptr)SampBuf);
  1116.                     DisposPtr((Ptr)theIbuf);
  1117.                     return(FALSE);
  1118.                 }
  1119.             }
  1120.             nSamps = nBytes / sizeof(int);
  1121.             for ( i = 0, Iptr = theIbuf, sp = SampBuf; i < nSamps; i++ ) {
  1122.                 *sp = (*Iptr++ * scalefactor);
  1123.                 if ( *sp < MinSample )
  1124.                     MinSample = *sp;
  1125.                 else if ( *sp > MaxSample )
  1126.                     MaxSample = *sp;
  1127.                 sp++;
  1128.             }
  1129.  
  1130.  
  1131.             nrec++;
  1132.             bytesLeft -= nBytes;
  1133.         }
  1134.  
  1135.     DisposPtr((Ptr)SampBuf);
  1136.     DisposPtr((Ptr)theIbuf);
  1137.     InitCursor();
  1138.  
  1139.  
  1140.     return(TRUE);
  1141. }
  1142.  
  1143. /*-------------------------------------------------------------------------------*/
  1144.  
  1145.  
  1146.  
  1147. Boolean    GetSFDir(DirName)
  1148.     Str255    *DirName;
  1149. {
  1150.     Str255        myStr;
  1151.     WDPBRec        myWDParamBlk;
  1152.     DirInfo        myCatInfoBlk;
  1153.     
  1154.     myCatInfoBlk.ioCompletion = NIL;
  1155.     myCatInfoBlk.ioVRefNum = -SFSaveDisk;
  1156.     myCatInfoBlk.ioDrDirID = CurDirStore;
  1157.     myCatInfoBlk.ioFDirIndex = -1;
  1158.     myCatInfoBlk.ioNamePtr = (StringPtr)myStr;
  1159.     if ( (theErr = PBGetCatInfo(&myCatInfoBlk, FALSE)) != noErr ) {
  1160.         PstringCopy((char *)theMess1, "\pError getting SoundFile Directory: PBGetCatInfo");
  1161.         NumToString(theErr, &theMess2);
  1162.         OSError(theMess1, theMess2);
  1163.         return(FALSE);
  1164.     }
  1165.     
  1166.     PstringCopy((char *)DirName, (char *)myStr);
  1167.     PstringCat((char *)DirName, "\p:");
  1168.     
  1169.     while (myCatInfoBlk.ioDrDirID != 2 ) {
  1170.         myCatInfoBlk.ioDrDirID = myCatInfoBlk.ioDrParID;
  1171.         if ( (theErr = PBGetCatInfo(&myCatInfoBlk, FALSE)) != noErr ) {
  1172.             PstringCopy((char *)theMess1, "\Error in GetSFDir: PBGetCatInfo");
  1173.             NumToString(theErr, &theMess2);
  1174.             OSError(theMess1, theMess2);
  1175.             return(FALSE);
  1176.         }
  1177.         PstringCat((char *)myStr, "\p:");
  1178.         PstringCat((char *)myStr, (char *)DirName);
  1179.         PstringCopy((char *)DirName, (char *)myStr);
  1180.     }
  1181.     CurDirStore = myCatInfoBlk.ioDrDirID;
  1182.     
  1183.     return(TRUE);
  1184. }
  1185.  
  1186.  
  1187. Boolean    SD1Info()
  1188. {
  1189.     register    double    x;
  1190.  
  1191.     register    int    i;
  1192.     WaveRec    Header;
  1193.     WavPtr    HeaderPtr;
  1194.     long    nBytes;
  1195.     OSErr    theErr;
  1196.     long    sampBufsz;
  1197.     long    bytesLeft;
  1198.     long    RecLength = 2048L;
  1199.     long    nSamps;
  1200.     Str255    aString;
  1201.     int        *theIbuf, *Iptr;
  1202.     
  1203. /* read the header */
  1204.     HeaderPtr = &Header;
  1205.     nBytes = sizeof(Header.HeaderSize);
  1206.     myIOParmBlk.ioPosMode = fsFromStart;
  1207.     myIOParmBlk.ioPosOffset = 0L;
  1208.     myIOParmBlk.ioBuffer = (Ptr)HeaderPtr;
  1209.     myIOParmBlk.ioReqCount = nBytes;
  1210.     theErr = PBRead(&myIOParmBlk, FALSE);
  1211.     if (theErr != noErr ) {
  1212.         if ( theErr == eofErr ) {
  1213.             PstringCopy((char *)theMess1, "\pEnd of file reached Header");
  1214.             errorAlert(theMess1, NIL);
  1215.             return(FALSE);
  1216.         }
  1217.         else {
  1218.             NumToString(theErr, &aString);
  1219.             PstringCopy((char *)theMess1, "\pError reading Header");
  1220.             errorAlert(theMess1, aString);
  1221.             return(FALSE);
  1222.         }
  1223.     }
  1224.     if ( myIOParmBlk.ioActCount != nBytes ) {
  1225.         PstringCopy((char *)theMess1, "\pError reading HeaderSize");
  1226.         errorAlert(theMess1, NIL);
  1227.     }
  1228.  
  1229.     nBytes = Header.HeaderSize;
  1230.     myIOParmBlk.ioPosMode = fsFromStart;
  1231.     myIOParmBlk.ioPosOffset = 0L;
  1232.     myIOParmBlk.ioBuffer = (Ptr)HeaderPtr;
  1233.     myIOParmBlk.ioReqCount = nBytes;
  1234.     theErr = PBRead(&myIOParmBlk, FALSE);
  1235.     if (theErr != noErr ) {
  1236.         if ( theErr == eofErr ) {
  1237.             PstringCopy((char *)theMess1, "\pEnd of file reached Header");
  1238.             errorAlert(theMess1, NIL);
  1239.             return(FALSE);
  1240.         }
  1241.         else {
  1242.             PstringCopy((char *)theMess1, "\pError reading Header");
  1243.             NumToString(theErr, &theMess2);
  1244.             errorAlert(theMess1, theMess2);
  1245.             return(FALSE);
  1246.         }
  1247.     }
  1248.     
  1249.     fileSize = Header.FileSize;
  1250.     SampleRate = Header.SampRate;
  1251.     
  1252.     if ( !SDnoResource )
  1253.         return(TRUE);
  1254. /* now scan the file to ascertain ma/min samples */
  1255.     sampBufsz  = RecLength;
  1256.     theIbuf = (int *)NewPtr(sizeof(int) * sampBufsz);
  1257.     if ( (theErr = MemError()) != noErr ) {
  1258.         PstringCopy((char *)theMess1, "\pcan't get enough memory for theIbuf");
  1259.         errorAlert(theMess1, NIL);
  1260.         return(FALSE);
  1261.     }    
  1262.     MinSample = 0.0;
  1263.     MaxSample = 0.0;
  1264.  
  1265.         
  1266.     bytesLeft = fileSize;
  1267.     nrec = 0;
  1268.  
  1269.     myIOParmBlk.ioPosMode = fsAtMark;
  1270.     myIOParmBlk.ioPosOffset = NIL;
  1271.  
  1272.     while ( bytesLeft > 0L ) {
  1273.         if ( bytesLeft > RecLength )
  1274.             nBytes = RecLength;
  1275.         else
  1276.             nBytes = bytesLeft;
  1277.             
  1278.         myIOParmBlk.ioBuffer = (Ptr)theIbuf;
  1279.         myIOParmBlk.ioReqCount = nBytes;
  1280.         theErr = PBRead(&myIOParmBlk, FALSE);
  1281.         if (theErr != noErr ) {
  1282.             if ( theErr == eofErr ) {
  1283.                 PstringCopy((char *)theMess1, "\pEnd of file");
  1284.                 errorAlert(theMess1, NIL);
  1285.                 return(FALSE);
  1286.             }
  1287.         }
  1288.         nBytes = myIOParmBlk.ioActCount;
  1289.         if ( nBytes != myIOParmBlk.ioReqCount ) {
  1290.             PstringCopy((char *)theMess1, "\pRead less bytes than expected");
  1291.             errorAlert(theMess1, NIL);
  1292.         }
  1293.         nSamps = nBytes / sizeof(int);
  1294.  
  1295.         for ( i = 0, Iptr = theIbuf; i < nSamps; i++ ) {
  1296.             x = (double)(*Iptr++);
  1297.             if ( x < MinSample )
  1298.                 MinSample = x;
  1299.             if ( x > MaxSample )
  1300.                 MaxSample = x;
  1301.         }
  1302.  
  1303.  
  1304.         nrec++;
  1305.     
  1306.             
  1307.         bytesLeft -= nBytes;
  1308.     }
  1309.     DisposPtr((Ptr)theIbuf);    
  1310.     return(TRUE);
  1311. }
  1312.  
  1313.  
  1314.  
  1315. Boolean    SD2Info()
  1316. {
  1317.     register    double    x;
  1318.  
  1319.     register    int    i;
  1320.     long    nBytes;
  1321.     OSErr    theErr;
  1322.     long    sampBufsz;
  1323.     long    bytesLeft;
  1324.     long    RecLength = 2048L;
  1325.     long    nSamps;
  1326.     int        *theIbuf, *Iptr;
  1327.  
  1328.     
  1329.     myIOParmBlk.ioCompletion = NIL;
  1330.     PBGetEOF(&myIOParmBlk, FALSE);
  1331.     if ( (fileSize = (long)myIOParmBlk.ioMisc) <= 0 ) {
  1332.         PstringCopy((char *)theMess1,"\pFile is empty!");
  1333.         errorAlert(theMess1, NIL);
  1334.         return(FALSE);
  1335.     }
  1336.     
  1337. /* now scan the file to ascertain max/min samples */
  1338.     sampBufsz  = RecLength;
  1339.     theIbuf = (int *)NewPtr(sizeof(int) * sampBufsz);
  1340.     if ( (theErr = MemError()) != noErr ) {
  1341.         PstringCopy((char *)theMess1, "\pcan't get enough memory  for theIbuf");
  1342.         errorAlert(theMess1, NIL);
  1343.         return(FALSE);
  1344.     }    
  1345.     MinSample = 0.0;
  1346.     MaxSample = 0.0;
  1347.  
  1348.         
  1349.     bytesLeft = fileSize;
  1350.     nrec = 0;
  1351.  
  1352.     myIOParmBlk.ioPosMode = fsAtMark;
  1353.     myIOParmBlk.ioPosOffset = NIL;
  1354.  
  1355.     while ( bytesLeft > 0L ) {
  1356.         if ( bytesLeft > RecLength )
  1357.             nBytes = RecLength;
  1358.         else
  1359.             nBytes = bytesLeft;
  1360.             
  1361.         myIOParmBlk.ioBuffer = (Ptr)theIbuf;
  1362.         myIOParmBlk.ioReqCount = nBytes;
  1363.         theErr = PBRead(&myIOParmBlk, FALSE);
  1364.         if (theErr != noErr ) {
  1365.             if ( theErr == eofErr ) {
  1366.                 PstringCopy((char *)theMess1, "\pEnd of file");
  1367.                 errorAlert(theMess1, NIL);
  1368.                 return(FALSE);
  1369.             }
  1370.         }
  1371.         nBytes = myIOParmBlk.ioActCount;
  1372.         if ( nBytes != myIOParmBlk.ioReqCount ) {
  1373.             PstringCopy((char *)theMess1, "\pRead less bytes than expected");
  1374.             errorAlert(theMess1, NIL);
  1375.         }
  1376.         nSamps = nBytes / sizeof(int);
  1377.  
  1378.         for ( i = 0, Iptr = theIbuf; i < nSamps; i++ ) {
  1379.             x = (double)(*Iptr++);
  1380.             if ( x < MinSample )
  1381.                 MinSample = x;
  1382.             if ( x > MaxSample )
  1383.                 MaxSample = x;
  1384.         }
  1385.  
  1386.  
  1387.         nrec++;
  1388.     
  1389.             
  1390.         bytesLeft -= nBytes;
  1391.     }
  1392.     DisposPtr((Ptr)theIbuf);    
  1393.     return(TRUE);
  1394. }
  1395.  
  1396.  
  1397. void    CheckSystem()
  1398. {
  1399.     
  1400.     theErr = SysEnvirons(1, &SysEnvData);
  1401.     if (SysEnvData.hasFPU)
  1402.         return;
  1403.     PstringCopy((char *)theMess1,"\pThis version of SFInfo requires a floating point unit");
  1404.     errorAlert(theMess1, NIL);
  1405.     ExitToShell();
  1406. }
  1407.  
  1408. void GetMusic4C_Prefs()
  1409. {
  1410.     int            refNum;
  1411.     StringPtr    volName;
  1412.     char        buffer[2];
  1413.     long        count;
  1414.     Str255        FileFormat;
  1415.     int    i;
  1416.     
  1417. /* "Music4C_Prefs" is kept in the System Folder */
  1418.     SFDirectoryName[0] = 0;
  1419.     theErr = FSOpen("\pMusic4C_Prefs", SysEnvData.sysVRefNum, &refNum);
  1420.     if (theErr == noErr) {
  1421.         count = 2L;
  1422.         theErr = FSRead (refNum, &count, &buffer);
  1423.         if ( theErr != noErr ) {
  1424.             PstringCopy((char *)theMess1, "\pError reading Preferences file");
  1425.             OSError(theMess1, NIL);
  1426.         }
  1427.         count = sizeof(FileFormat);
  1428.         theErr = FSRead (refNum, &count, &FileFormat);
  1429.         if ( theErr != noErr ) {
  1430.             PstringCopy((char *)theMess1, "\pError reading Preferences file");
  1431.             OSError(theMess1, NIL);
  1432.         }
  1433.         count = sizeof(SFDirectoryName);
  1434.         theErr = FSRead (refNum, &count, &SFDirectoryName);
  1435.         if ( theErr != noErr ) {
  1436.             PstringCopy((char *)theMess1, "\pError reading Preferences file");
  1437.             OSError(theMess1, NIL);
  1438.         }
  1439.         theErr = FSClose(refNum);
  1440.     }
  1441. }
  1442.